﻿#include "ApiCommand.h"
#include <QCoreApplication>
#include <iostream>
#include <qt_windows.h>
#include <QtCore/QtCore>
#include "QUuid"
#include <Psapi.h>
#include "Toolhelp.h"

ApiCommand::ApiCommand(QObject *parent)
    : QObject(parent)
{

}

int ApiCommand::execute()
{
    const QStringList& argVec = qApp->arguments();
    if (argVec.at(1) == "WritePrivateProfileString")
    {
        return Api_WritePrivateProfileString();
    }
    if (argVec[1] == "GetPrivateProfileString")
    {
        return Api_GetPrivateProfileString();
    }
    if (argVec[1] == "RegSetValue")
    {
        return Api_RegSetValue();
    }
    if (argVec[1] == "RegQueryValue")
    {
        return Api_RegQueryValue();
    }
    if (argVec[1] == "Sleep")
    {
        return Api_Sleep();
    }
    if (argVec[1] == "GetProcessIdByFullName")
    {
        return Api_GetProcessIdByFullName();
    }
    if (argVec[1] == "GetProcessIdByPathStartWith")
    {
        return Api_GetProcessIdByPathStartWith();
    }
    if (argVec[1] == "KillProcessByPID")
    {
        return Api_KillProcessByPID();
    }
    if (argVec[1] == "KillProcessByFullName")
    {
        return Api_KillProcessByFullName();
    }
    if (argVec[1] == "KillProcessByPathStartWith")
    {
        return Api_KillProcessByPathStartWith();
    }
    return 0;
}


int ApiCommand::Api_WritePrivateProfileString()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 6)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：WritePrivateProfileString sGroup sKey sValue sFile" << std::endl;
        return 1;
    }

    QString sGroup = argVec.at(2);
    QString sKey   = argVec.at(3);
    QString sValue = argVec.at(4);
    QString sFile  = argVec.at(5);
    return WritePrivateProfileStringAC(sGroup, sKey, sValue, sFile);
}

int ApiCommand::Api_GetPrivateProfileString()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 6)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：GetPrivateProfileString sGroup sKey sDefault sFile" << std::endl;
        return 1;
    }

    QString sGroup = argVec.at(2);
    QString sKey = argVec.at(3);
    QString sDefault = argVec.at(4);
    QString sFile = argVec.at(5);
    return GetPrivateProfileStringAC(sGroup, sKey, sDefault, sFile);
}

int ApiCommand::Api_RegSetValue()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 5)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：RegSetValue sRoot sApp sKey sValue" << std::endl;
        return 1;
    }
    QString sRoot = argVec.at(2);
    QString sApp = argVec.at(3);
    QString sKey = argVec.at(4);
    QString sValue = argVec.at(5);

    sApp = QDir::toNativeSeparators(sRoot + "/" + sApp);
    QSettings regSettings(sApp, QSettings::NativeFormat);
    regSettings.setValue(sKey, sValue);
    if (regSettings.status() == QSettings::NoError)
    {
        return 0;
    }
    
    return 1;
}

int ApiCommand::Api_RegQueryValue()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 5)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：RegQueryValue sRoot sApp sKey sDefault" << std::endl;
        return 1;
    }
    QString sRoot = argVec.at(2);
    QString sApp = argVec.at(3);
    QString sKey = argVec.at(4);
    QString sDefault = argVec.at(5);
    QString sValue = sDefault;

    sRoot = QDir::toNativeSeparators(sRoot);
    sKey = sApp + "/" + sKey;
    QSettings regSettings(sRoot, QSettings::NativeFormat);
    if (regSettings.contains(sKey))
    {
        sValue = regSettings.value(sKey, sDefault).toString();
    }
    std::wcout << sValue.toStdWString();

    return 0;
}


int ApiCommand::Api_Sleep()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 3)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：Sleep Milliseconds" << std::endl;
        return 1;
    }

    QString sMilliseconds = argVec.at(2);
    int iMs = sMilliseconds.toInt();
    if (iMs < 1)
    {
        return 2;
    }

    ::Sleep(iMs);
    
    return 0;
}

int ApiCommand::Api_GetProcessIdByFullName()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 3)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：GetProcessIdByFullName FileFullName" << std::endl;
        return 1;
    }
    QString sFileFullName = argVec.at(2);
    sFileFullName = QDir::toNativeSeparators(sFileFullName);

    CToolhelp::EnablePrivilege(SE_DEBUG_NAME, TRUE);

    CToolhelp th(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { sizeof(pe) };
    BOOL fOk = th.ProcessFirst(&pe);
    for (; fOk; fOk = th.ProcessNext(&pe))
    {
        CToolhelp thModule(TH32CS_SNAPMODULE, pe.th32ProcessID);
        MODULEENTRY32 pme = { sizeof(pme) };
        BOOL mOk = thModule.ModuleFirst(&pme);
        QString strExePath = QString::fromWCharArray(pme.szExePath);
        if (strExePath == sFileFullName)
        {
            std::wcout << QString::number(pe.th32ProcessID).toStdWString() << std::endl;
        }
    }
    return 0;
}

int ApiCommand::Api_GetProcessIdByPathStartWith()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 3)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：GetProcessIdByPathStartWith PathPrefix" << std::endl;
        return 1;
    }
    QString sPathPrefix = argVec.at(2);
    sPathPrefix = QDir::toNativeSeparators(sPathPrefix);

    CToolhelp::EnablePrivilege(SE_DEBUG_NAME, TRUE);

    CToolhelp th(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { sizeof(pe) };
    BOOL fOk = th.ProcessFirst(&pe);
    for (; fOk; fOk = th.ProcessNext(&pe))
    {
        CToolhelp thModule(TH32CS_SNAPMODULE, pe.th32ProcessID);
        MODULEENTRY32 pme = { sizeof(pme) };
        BOOL mOk = thModule.ModuleFirst(&pme);
        QString strExePath = QString::fromWCharArray(pme.szExePath);
        if (strExePath.startsWith(sPathPrefix))
        {
            std::wcout << QString::number(pe.th32ProcessID).toStdWString() << std::endl;
        }
    }
    return 0;
}

int ApiCommand::Api_KillProcessByPID()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 3)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：KillProcessByPID PID1 [PID2 ...]" << std::endl;
        return 1;
    }
    QStringList listPID = argVec.mid(2);

    CToolhelp::EnablePrivilege(SE_DEBUG_NAME, TRUE);

    KillProcessByPidAC(listPID);

    return 0;
}

int ApiCommand::Api_KillProcessByFullName()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 3)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：KillProcessByFullName FileFullName" << std::endl;
        return 1;
    }
    QString sFileFullName = argVec.at(2);
    sFileFullName = QDir::toNativeSeparators(sFileFullName);

    CToolhelp::EnablePrivilege(SE_DEBUG_NAME, TRUE);

    QStringList listPID;
    CToolhelp th(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { sizeof(pe) };
    BOOL fOk = th.ProcessFirst(&pe);
    for (; fOk; fOk = th.ProcessNext(&pe))
    {
        CToolhelp thModule(TH32CS_SNAPMODULE, pe.th32ProcessID);
        MODULEENTRY32 pme = { sizeof(pme) };
        BOOL mOk = thModule.ModuleFirst(&pme);
        QString strExePath = QString::fromWCharArray(pme.szExePath);
        if (strExePath == sFileFullName)
        {
            listPID.append(QString::number(pe.th32ProcessID));
        }
    }

    KillProcessByPidAC(listPID);

    return 0;
}

int ApiCommand::Api_KillProcessByPathStartWith()
{
    const QStringList& argVec = qApp->arguments();
    int argCount = argVec.size();
    if (argCount < 3)
    {
        std::wcerr << L"##ERROR##1" << std::endl;
        std::wcerr << L"参数：KillProcessByPathStartWith PathPrefix" << std::endl;
        return 1;
    }
    QString sPathPrefix = argVec.at(2);
    sPathPrefix = QDir::toNativeSeparators(sPathPrefix);

    CToolhelp::EnablePrivilege(SE_DEBUG_NAME, TRUE);

    QStringList listPID;
    CToolhelp th(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { sizeof(pe) };
    BOOL fOk = th.ProcessFirst(&pe);
    for (; fOk; fOk = th.ProcessNext(&pe))
    {
        CToolhelp thModule(TH32CS_SNAPMODULE, pe.th32ProcessID);
        MODULEENTRY32 pme = { sizeof(pme) };
        BOOL mOk = thModule.ModuleFirst(&pme);
        QString strExePath = QString::fromWCharArray(pme.szExePath);
        if (strExePath.startsWith(sPathPrefix))
        {
            listPID.append(QString::number(pe.th32ProcessID));
        }
    }

    KillProcessByPidAC(listPID);

    return 0;
}


int ApiCommand::WritePrivateProfileStringAC(QString strGroup, QString strKey, QString strValue, QString strFile)
{
    std::wstring sGroup = strGroup.toStdWString();
    std::wstring sKey = strKey.toStdWString();
    std::wstring sValue = strValue.toStdWString();
    std::wstring sFile = QFileInfo(strFile).absoluteFilePath().toStdWString();
    bool bRet3 = ::WritePrivateProfileString(sGroup.data(), sKey.data(), sValue.data(), sFile.data());
    if (bRet3)
    {
        std::wcout << L"##OK##" << std::endl;
        return 0;
    }

    std::wcerr << L"##ERROR##2" << std::endl;
    return 2;
}

int ApiCommand::GetPrivateProfileStringAC(QString strGroup, QString strKey, QString strDefault, QString strFile)
{
    std::wstring sGroup = strGroup.toStdWString();
    std::wstring sKey = strKey.toStdWString();
    std::wstring sDefault = strDefault.toStdWString();
    std::wstring sFile = QFileInfo(strFile).absoluteFilePath().toStdWString();
    std::wstring sValue(1024, 0);
    DWORD length = ::GetPrivateProfileString(sGroup.data(), sKey.data(), sDefault.data(), (LPWSTR)sValue.data(), sValue.size() - 1, sFile.data());
    sValue.resize(length);
    std::wcout << sValue;
    return 0;
}

int ApiCommand::KillProcessByPidAC(QStringList listPID)
{
    const DWORD dwCurrProcessId = ::GetCurrentProcessId();

    for each (QString sPid in listPID)
    {
        DWORD dwProcessId = sPid.toInt();
        if (dwProcessId <= 4)
        {
            continue;
        }
        if (dwProcessId == dwCurrProcessId)
        {
            continue;
        }
        HANDLE hYourTargetProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId);
        if (NULL == hYourTargetProcess)
        {
            continue;
        }
        BOOL bSuccess = TerminateProcess(hYourTargetProcess, 4);
        CloseHandle(hYourTargetProcess);

        if (bSuccess)
        {
            std::wcout << L"已终止进程" << sPid.toStdWString() << std::endl;
        }
        else
        {
            std::wcout << L"无法终止进程" << sPid.toStdWString() << std::endl;
        }
    }

    return 0;
}
